package com.jh.paymentchannel.service;

import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.net.URI;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import com.jh.paymentchannel.util.Util;
import com.jh.paymentchannel.util.yeepay.Digest;
import net.sf.json.JSONObject;


@Controller
@EnableAutoConfiguration
public class YBPayCallBackService {

	private static final Logger log = LoggerFactory.getLogger(YBPayCallBackService.class);

	//private static String key = Conts.hmacKey; // 商户秘钥

	/**
	 * 商户秘钥
	 */
	//@Value("${yibao.hmacKey}")
	private static String hmacKey;

	//生产商编号
	//@Value("${yibao.customerNumber}")
	private static String customerNumber;


	//@Value("${yibao.baseRequestUrl}")
	private String baseRequestUrl;



	/**
	 * 请求参数 验签在数组最后
	 */
	private static NameValuePair[] param = {
			// 出款金额
			new NameValuePair("amount", ""),
			// 小商户编号
			new NameValuePair("customerNumber", ""),
			// 出款订单号
			new NameValuePair("externalNo", ""),
			// 大商户编号
			new NameValuePair("mainCustomerNumber", ""),
			
			// 出款方式
			new NameValuePair("transferWay", ""),
			
			new NameValuePair("callBackUrl",""),
			
			// 签名串
			new NameValuePair("hmac", ""),
			
	};
	
	@Autowired
	Util util;
	
	@Value("${payment.ipAddress}")
	private String ipAddress;
	
	@RequestMapping(method=RequestMethod.POST,value="/v1.0/paymentchannel/topup/yb/notify_call")
	public @ResponseBody void notifycall(HttpServletRequest req, HttpServletResponse res) throws IOException{
				log.info("进入易宝回调接口================"+req.getParameterMap().toString());
				// 获取支付报文参数
				Map<String, String[]> params = req.getParameterMap();
				log.info("params================"+params);
				Map<String, String> map = new HashMap<String, String>();
				for (String key : params.keySet()) {
					String[] values = params.get(key);
					if (values.length > 0) {
						map.put(key, values[0]);
					}
				}
				PrintWriter pw = res.getWriter();
				if(map.containsKey("transferStatus")) {
					String transferStatus = map.get("transferStatus");
					if("RECEIVED".equalsIgnoreCase(transferStatus)||"PROCESSING".equalsIgnoreCase(transferStatus)||"SUCCESSED".equalsIgnoreCase(transferStatus)) {
						String ordercode = map.get("externalNo");
						String externalld = map.get("serialNo");
	            		/**调用下单，需要得到用户的订单信息*/
						RestTemplate restTemplate=new RestTemplate();
						URI uri = util.getServiceUrl("transactionclear", "error url request!");
						String url = uri.toString() + "/v1.0/transactionclear/payment/update";
						/**根据的用户手机号码查询用户的基本信息*/
						MultiValueMap<String, String> requestEntity  = new LinkedMultiValueMap<String, String>();
						requestEntity.add("status", "1");
						requestEntity.add("third_code", externalld);
						requestEntity.add("order_code", ordercode);
						log.info("接口/v1.0/transactionclear/payment/update--参数================"+ordercode+","+externalld);
						String result = restTemplate.postForObject(url, requestEntity, String.class);
						log.info("接口/v1.0/transactionclear/payment/update--RESULT================"+result);
						/**判断是否有外放的通道的处理， 如果有那么继续回调外放哦*/
						uri = util.getServiceUrl("transactionclear", "error url request!");
						url = uri.toString() + "/v1.0/transactionclear/payment/query/ordercode";
						
						
						requestEntity  = new LinkedMultiValueMap<String, String>();
						requestEntity.add("order_code",  ordercode);
						result = restTemplate.postForObject(url, requestEntity, String.class);
						log.info("接口/v1.0/transactionclear/payment/query/ordercode--RESULT================"+result);
						JSONObject jsonObject =  JSONObject.fromObject(result);
						JSONObject resultObj  =  jsonObject.getJSONObject("result");
						String outMerOrdercode  =  resultObj.getString("outMerOrdercode");
						String orderdesc        =  resultObj.getString("desc");
						String phone            =  resultObj.getString("phone");
						String  tranamount      =  resultObj.getString("amount");
						String channelTag       =  resultObj.getString("channelTag");
						String notifyURL        =  resultObj.getString("outNotifyUrl");
						if(outMerOrdercode != null && !outMerOrdercode.equalsIgnoreCase("")){
							uri = util.getServiceUrl("channel", "error url request!");
							url = uri.toString() + "/v1.0/channel/callback/yilian/notify_call";
							requestEntity  = new LinkedMultiValueMap<String, String>();
							requestEntity.add("merchant_no",  phone);
							requestEntity.add("amount",  tranamount);
							requestEntity.add("channel_tag",  channelTag);
							requestEntity.add("order_desc",  URLEncoder.encode(orderdesc, "UTF-8"));
							requestEntity.add("order_code",  outMerOrdercode);
							requestEntity.add("sys_order",   ordercode);
							requestEntity.add("notify_url", URLEncoder.encode(notifyURL, "UTF-8"));
							result = restTemplate.postForObject(url, requestEntity, String.class);
						}
						pw.write("success");
	            	
					}
					
				}else {
					log.info("map================"+map);
					String status = map.get("status");
					log.info("status================"+status);
					
					if(status.equalsIgnoreCase("SUCCESS")) {
						log.info("==========================welcome========================");
						String ordercode = map.get("requestId");
						
						RestTemplate restTemplate=new RestTemplate();
						URI uri = util.getServiceUrl("transactionclear", "error url request!");
						String url = uri.toString() + "/v1.0/transactionclear/payment/query/ordercode";
						MultiValueMap<String, String> requestEntity  = new LinkedMultiValueMap<String, String>();
						requestEntity.add("order_code", ordercode);
						String result = restTemplate.postForObject(url, requestEntity, String.class);
						log.info("接口/v1.0/transactionclear/payment/query/ordercode--RESULT================"+result);
						JSONObject jsonObject =  JSONObject.fromObject(result);
						JSONObject resultObj  =  jsonObject.getJSONObject("result");
						String realAmt =  resultObj.getString("realAmount");
						String extraFee = resultObj.getString("extraFee");
						realAmt = String.valueOf(Integer.valueOf(realAmt.substring(0, realAmt.indexOf(".")))+Integer.valueOf(extraFee.substring(0, extraFee.indexOf("."))))+realAmt.substring(realAmt.indexOf("."), realAmt.length());
						BigDecimal b1 = new BigDecimal(realAmt);  
						BigDecimal b2 = new BigDecimal("0.01");  
						String realAmount = String.valueOf(new Double(b1.subtract(b2).doubleValue()));
						String externalld = map.get("externalld");
						String amount = map.get("amount");
						String customerNumber = map.get("customerNumber");
						String mainCustomerNumber = customerNumber; // 代理商编码
						log.info("==============="+ordercode+","+externalld+","+amount+","+customerNumber+","+mainCustomerNumber);
						param[0].setValue(realAmount);
						param[1].setValue(customerNumber);
						param[2].setValue(ordercode);
						param[3].setValue(mainCustomerNumber);
						param[4].setValue("1");
						param[5].setValue(ipAddress+"/v1.0/paymentchannel/topup/yb/notify_call");
						param[param.length - 1].setValue(hmacSign());
						PostMethod postMethod = new PostMethod("https://skb.yeepay.com/skb-app/withDrawApi.action");
						HttpClient client = new HttpClient();
						postMethod.addRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
						try {
							postMethod.setRequestBody(param);
							int status2 = client.executeMethod(postMethod);
							log.info("==========结算status2=========="+status2);
							String backinfo = postMethod.getResponseBodyAsString();
							log.info("==========结算backinfo=========="+backinfo);
							if (status2 == HttpStatus.SC_OK) {
								JSONObject obj = JSONObject.fromObject(backinfo);
								if(obj.getString("code").equals("0000")) {
									/**调用下单，需要得到用户的订单信息*/
									restTemplate=new RestTemplate();
									uri = util.getServiceUrl("transactionclear", "error url request!");
									url = uri.toString() + "/v1.0/transactionclear/payment/update";
									/**根据的用户手机号码查询用户的基本信息*/
									requestEntity  = new LinkedMultiValueMap<String, String>();
									requestEntity.add("status", "1");
									requestEntity.add("third_code", externalld);
									requestEntity.add("order_code", ordercode);
									log.info("接口/v1.0/transactionclear/payment/update--参数================"+ordercode+","+externalld);
									result = restTemplate.postForObject(url, requestEntity, String.class);
									log.info("接口/v1.0/transactionclear/payment/update--RESULT================"+result);
									/**判断是否有外放的通道的处理， 如果有那么继续回调外放哦*/
									uri = util.getServiceUrl("transactionclear", "error url request!");
									url = uri.toString() + "/v1.0/transactionclear/payment/query/ordercode";
									
									
									requestEntity  = new LinkedMultiValueMap<String, String>();
									requestEntity.add("order_code",  ordercode);
									result = restTemplate.postForObject(url, requestEntity, String.class);
									log.info("接口/v1.0/transactionclear/payment/query/ordercode--RESULT================"+result);
									jsonObject =  JSONObject.fromObject(result);
									resultObj  =  jsonObject.getJSONObject("result");
									String outMerOrdercode  =  resultObj.getString("outMerOrdercode");
									String orderdesc        =  resultObj.getString("desc");
									String phone            =  resultObj.getString("phone");
									String  tranamount      =  resultObj.getString("amount");
									String channelTag       =  resultObj.getString("channelTag");
									String notifyURL        =  resultObj.getString("outNotifyUrl");
									if(outMerOrdercode != null && !outMerOrdercode.equalsIgnoreCase("")){
										uri = util.getServiceUrl("channel", "error url request!");
										url = uri.toString() + "/v1.0/channel/callback/yilian/notify_call";
										requestEntity  = new LinkedMultiValueMap<String, String>();
										requestEntity.add("merchant_no",  phone);
										requestEntity.add("amount",  tranamount);
										requestEntity.add("channel_tag",  channelTag);
										requestEntity.add("order_desc",  URLEncoder.encode(orderdesc, "UTF-8"));
										requestEntity.add("order_code",  outMerOrdercode);
										requestEntity.add("sys_order",   ordercode);
										requestEntity.add("notify_url", URLEncoder.encode(notifyURL, "UTF-8"));
										result = restTemplate.postForObject(url, requestEntity, String.class);
									}
									pw.write("success");
								}else {
									status2 = client.executeMethod(postMethod);
									backinfo = postMethod.getResponseBodyAsString();
									log.info("==========结算backinfo=========="+backinfo);
									obj = JSONObject.fromObject(backinfo);
									if(obj.getString("code").equals("0000")) {
										/**调用下单，需要得到用户的订单信息*/
										restTemplate=new RestTemplate();
										
										uri = util.getServiceUrl("transactionclear", "error url request!");
										url = uri.toString() + "/v1.0/transactionclear/payment/update";
										
										/**根据的用户手机号码查询用户的基本信息*/
										requestEntity  = new LinkedMultiValueMap<String, String>();
										requestEntity.add("status", "1");
										requestEntity.add("third_code", externalld);
										requestEntity.add("order_code", ordercode);
										log.info("接口/v1.0/transactionclear/payment/update--参数================"+ordercode+","+externalld);
										result = restTemplate.postForObject(url, requestEntity, String.class);
										log.info("接口/v1.0/transactionclear/payment/update--RESULT================"+result);
										/**判断是否有外放的通道的处理， 如果有那么继续回调外放哦*/
										uri = util.getServiceUrl("transactionclear", "error url request!");
										url = uri.toString() + "/v1.0/transactionclear/payment/query/ordercode";
										
										
										requestEntity  = new LinkedMultiValueMap<String, String>();
										requestEntity.add("order_code",  ordercode);
										result = restTemplate.postForObject(url, requestEntity, String.class);
										log.info("接口/v1.0/transactionclear/payment/query/ordercode--RESULT================"+result);
										jsonObject =  JSONObject.fromObject(result);
										resultObj  =  jsonObject.getJSONObject("result");
										String outMerOrdercode  =  resultObj.getString("outMerOrdercode");
										String orderdesc        =  resultObj.getString("desc");
										String phone            =  resultObj.getString("phone");
										String  tranamount      =  resultObj.getString("amount");
										String channelTag       =  resultObj.getString("channelTag");
										String notifyURL        =  resultObj.getString("outNotifyUrl");
										if(outMerOrdercode != null && !outMerOrdercode.equalsIgnoreCase("")){
											uri = util.getServiceUrl("channel", "error url request!");
											url = uri.toString() + "/v1.0/channel/callback/yilian/notify_call";
											requestEntity  = new LinkedMultiValueMap<String, String>();
											requestEntity.add("merchant_no",  phone);
											requestEntity.add("amount",  tranamount);
											requestEntity.add("channel_tag",  channelTag);
											requestEntity.add("order_desc",  URLEncoder.encode(orderdesc, "UTF-8"));
											requestEntity.add("order_code",  outMerOrdercode);
											requestEntity.add("sys_order",   ordercode);
											requestEntity.add("notify_url", URLEncoder.encode(notifyURL, "UTF-8"));
											result = restTemplate.postForObject(url, requestEntity, String.class);
										}
										pw.write("success");
									}else {
										pw.write("fail");
									}
								}
							} else if (status2 == HttpStatus.SC_MOVED_PERMANENTLY
									|| status2 == HttpStatus.SC_MOVED_TEMPORARILY) {
								// 从头中取出转向的地址
								Header locationHeader = postMethod
										.getResponseHeader("location");
								String location = null;
								if (locationHeader != null) {
									location = locationHeader.getValue();
									System.out
									.println("The page was redirected to:" + location);
								} else {
									System.err.println("Location field value is null.");
								}
							} else {
								System.out.println("fail======" + status2);
							}
						} catch (Exception e) {
							e.printStackTrace();
						} finally {
							// 释放连接
							postMethod.releaseConnection();
						}
					}else {
						pw.write("fail");
					}
					
				}
				pw.flush();
				pw.close();

				
	       
	}
	/**
	 * 签名
	 *
	 * @return
	 */
	private static String hmacSign() {
		StringBuilder hmacStr = new StringBuilder();
		for (NameValuePair nameValuePair : param) {
			if (nameValuePair.getName().equals("hmac")) {
				continue;
			}
			hmacStr.append(nameValuePair.getValue() == null ? ""
					: nameValuePair.getValue());
			
		}

		log.info("===============");
		log.info("hmacStr.toString()=" + hmacStr.toString());
		log.info("===============");
		
		String hmac = Digest.hmacSign(hmacStr.toString(), hmacKey);

		log.info("===============");
		log.info("hmac=" + hmac);
		log.info("===============");
		
		return hmac;
	}
	
}
class CustomerInforUpdatePartsBuilder {

    private List<Part> parts = new ArrayList<Part>();

    public Part[] generateParams() {
        return parts.toArray(new Part[parts.size()]);
    }

    public CustomerInforUpdatePartsBuilder setMainCustomerNumber(
            String mainCustomerNumber) {
        this.parts.add(new StringPart("mainCustomerNumber",
                mainCustomerNumber == null ? "" : mainCustomerNumber, "UTF-8"));
        return this;
    }

    public CustomerInforUpdatePartsBuilder setCustomerNumber(
            String customerNumber) {
        this.parts.add(new StringPart("customerNumber",
                customerNumber == null ? "" : customerNumber, "UTF-8"));
        return this;
    }

    public CustomerInforUpdatePartsBuilder setWhiteList(String whiteList) {
        this.parts.add(new StringPart("whiteList", whiteList == null ? ""
                : whiteList, "UTF-8"));
        return this;
    }

    public CustomerInforUpdatePartsBuilder setFreezeDays(String freezeDays) {
        this.parts.add(new StringPart("freezeDays", freezeDays == null ? ""
                : freezeDays, "UTF-8"));
        return this;
    }

    public CustomerInforUpdatePartsBuilder setHmac(String hmac) {
        this.parts
                .add(new StringPart("hmac", hmac == null ? "" : hmac, "UTF-8"));
        return this;
    }

    public CustomerInforUpdatePartsBuilder setModifyType(String modifyType) {
        this.parts.add(new StringPart("modifyType", modifyType == null ? ""
                : modifyType, "UTF-8"));
        return this;
    }

    public CustomerInforUpdatePartsBuilder setBankCardNumber(
            String bankCardNumber) {
        this.parts.add(new StringPart("bankCardNumber",
                bankCardNumber == null ? "" : bankCardNumber, "UTF-8"));
        return this;
    }

    public CustomerInforUpdatePartsBuilder setBankName(String bankName) {
        this.parts.add(new StringPart("bankName", bankName == null ? ""
                : bankName, "UTF-8"));
        return this;
    }

    public CustomerInforUpdatePartsBuilder setRiskReserveDay(
            String riskReserveDay) {
        this.parts.add(new StringPart("riskReserveDay",
                riskReserveDay == null ? "" : riskReserveDay, "UTF-8"));
        return this;
    }

    public CustomerInforUpdatePartsBuilder setManualSettle(String manualSettle) {
        this.parts.add(new StringPart("manualSettle", manualSettle == null ? ""
                : manualSettle, "UTF-8"));
        return this;
    }

    public CustomerInforUpdatePartsBuilder setSplitter(String splitter) {
        this.parts.add(new StringPart("splitter", splitter == null ? ""
                : splitter, "UTF-8"));
        return this;
    }

    public CustomerInforUpdatePartsBuilder setSplitterProfitFee(
            String splitterProfitFee) {
        this.parts.add(new StringPart("splitterProfitFee",
                splitterProfitFee == null ? "" : splitterProfitFee, "UTF-8"));
        return this;
    }

    public CustomerInforUpdatePartsBuilder setBusiness(String business) {
        this.parts.add(new StringPart("business", business == null ? ""
                : business, "UTF-8"));
        return this;
    }
}

